#!/usr/bin/python3.6
# -*- coding: utf-8 -*

import os
import socket
import json
from pathlib import Path
import shutil
import time

# k8s_plan.json
k8s_plan = '''
    {
        "master_info":[{"ipaddr":"192.168.62.131"},{"hostname":"k8s-master.mageedu.com"}],
        "node01_info":[{"ipaddr":"192.168.62.130"},{"hostname":"k8s-node01.mageedu.com"}],
        "node02_info":[{"ipaddr":"192.168.62.129"},{"hostname":"k8s-node02.mageedu.com"}],
        "k8s_version":"1.23.1"
    }
'''

# 字符串转json
dict_plan = json.loads(k8s_plan)
master_info = dict_plan['master_info']
node01_info = dict_plan['node01_info']
node02_info = dict_plan['node02_info']
k8s_version = dict_plan['k8s_version']
master_ipaddr, master_hostname = master_info
node01_ipaddr, node01_hostname = node01_info
node02_ipaddr, node02_hostname = node02_info

# # 全局变量
# with open('/root/k8s_plan.json', 'r') as f:
#     data = f.read()
#
#     dict_plan = json.loads(data)
#
#     master_info = dict_plan['master_info']
#     node01_info = dict_plan['node01_info']
#     node02_info = dict_plan['node02_info']
#     k8s_version = dict_plan['k8s_version']
#     master_ipaddr, master_hostname = master_info
#     node01_ipaddr, node01_hostname = node01_info
#     node02_ipaddr, node02_hostname = node02_info

# 关闭防火墙，并将返回结果丢到黑洞
def stop_firewalld():
    cmds = [
        'systemctl stop firewalld >> /dev/null',
        'systemctl disable firewalld >> /dev/null',
        'systemctl stop NetworkManager >> /dev/null',
        ' systemctl disable NetworkManager >> /dev/null'
    ]

    for cmd in cmds:
        if os.system(cmd) == 0:
            result = cmd, '执行命令成功'

            print(result)

# 设置hosts文件
def setting_hosts():
    data = [
        '%s %s\n' % (master_ipaddr['ipaddr'], master_hostname['hostname']),
        '%s %s\n' % (node01_ipaddr['ipaddr'], node01_hostname['hostname']),
        '%s %s\n' % (node02_ipaddr['ipaddr'], node02_hostname['hostname'])
    ]
    with open('/etc/hosts', 'r') as f:
        file_data = f.readlines()
        for i in data:
            if i in file_data:
                print(i, '存在于hosts文件里无需更改')
            else:
                with open('/etc/hosts', 'a') as f:
                    f.write(i)
                    print('添加映射关系%s到hosts文件内' % (i))


def stop_selinux(old_str, new_str):
    with open('/etc/selinux/config', 'r') as f:
        data = f.read()
        if new_str in data:
            return 'sellinux已修改!'
        new_Data = data.replace(old_str, new_str)

        with open('/etc/selinux/config', 'w') as f:
            f.writelines(new_Data)

            return '关闭selinux成功!'


def add_Ipv6Rule():
    with open('/etc/sysctl.conf', 'r') as f:
        data = f.read()
        if 'net.bridge.bridge-nf-call-ip6tables = 1' in data and 'net.bridge.bridge-nf-call-iptables = 1' in data:
            return '已开启ipv4和ipv6的转发规则'
        with open('/etc/sysctl.conf', 'a') as f:
            data = [
                'net.bridge.bridge-nf-call-ip6tables = 1\n',
                'net.bridge.bridge-nf-call-iptables = 1\n'
            ]
            f.writelines(data)

        if os.system('modprobe br_netfilter >> /dev/null') == 0 and os.system('sysctl -p >> /dev/null') == 0:
            return '开启ip转发规则成功!'


def stop_swap(old_str, new_str):
    os.system('swapoff -a >> /dev/null')
    with open('/etc/fstab', 'r') as f:
        data = f.read()
        if new_str in data:
            return 'swap已经永久关闭'
        with open('/etc/fstab', 'w') as f:
            new_Data = data.replace(old_str, new_str)
            f.writelines(new_Data)
            return '永久关闭swap成功'


def install_docker():
    cmds = [
        'yum -y install yum-utils device-mapper-presistent-data lvm2 >> /dev/null',
        'yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo >> /dev/null',
        'yum -y install docker-ce docker-ce-cli containerd.io >> /dev/null',
        'systemctl start docker >> /dev/null'
    ]
    print('~~~~~~~~~~正在部署docker和配置docker加速预计个把分钟请耐心等待~~~~~~~~~~~~~')
    for cmd in cmds:
        if os.system(cmd) == 0:
            print(cmd, '执行成功!')

    with open('/etc/docker/daemon.json', 'w') as f:
        data = [
            '{\n',
            '"registry-mirrors": [\n',
            '   "https://docker.mirrors.ustc.edu.cn",\n',
            '   "https://hub-mirror.c.163.com",\n',
            '   "https://reg-mirror.qiniu.com",\n',
            '   "https://registry.docker-cn.com"\n'
            ' ],\n',
            '"exec-opts": ["native.cgroupdriver=systemd"],\n',
            '"log-driver": "json-file",\n',
            '"log-opts": {\n',
            '   "max-size": "200m"\n',
            '},\n',
            '"storage-driver": "overlay2"\n',
            '}\n',
        ]
        f.writelines(data)
    time.sleep(1)
    cmds = [
        'sudo systemctl daemon-reload',
        'sudo systemctl restart docker',
    ]
    for cmd in cmds:
        print(cmd, '执行成功')
        os.system(cmd)
    CgroupDriver = os.popen('docker info | grep -w "Cgroup Driver"').read()
    print(CgroupDriver)


def setting_YumRepo():
    base_dir = '/etc/yum.repos.d/'

    # 创建bak目录

    back_dir = Path(base_dir) / 'bak'

    if not back_dir.exists():
        back_dir.mkdir()

        # basedir下的所有文件移动back_dir下
        for file in Path(base_dir).iterdir():
            if file.is_file():
                shutil.move(file, back_dir / file.name)
                # print(file.name)

        for file in Path(back_dir).iterdir():
            if file.is_file() and file.name == 'CentOS-Base.repo':
                shutil.move(file, Path(base_dir) / file.name)

        if os.system("sed -e 's|^mirrorlist=|#mirrorlist=|g' \
                    -e 's|^#baseurl=http://mirror.centos.org/centos|baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos|g' \
                    -i.bak \
                    /etc/yum.repos.d/CentOS-*.repo") == 0:
            return '配置清华源镜像成功!'
        return '配置清华源镜像失败!'
    return '脚本检测到/etc/yum.repos.d/bak目录已存在,如果已经配好了yum源则不需要管,如果没配好请把bak目录下的文件移出来然后删除bak目录'


def editHostName():
    hostname = socket.gethostname()
    ip = socket.gethostbyname(hostname)
    with open('/etc/hosts', 'r') as f:
        data = f.readlines()
        for line in data:
            if ip in line:
                ipaddr, domain = line.split()
                set_hostname = 'hostname %s' % (domain)
                if os.system(set_hostname) == 0:
                    print(set_hostname, '执行成功!')
                    with open('/etc/hostname', 'w') as f:
                        f.write(domain + '\n')
                        print('设置hostname成功重启后生效(根据hosts文件)')


def setting_k8sRepo():
    data = [
        '[kubernetes]\n',
        'name=Kubernetes\n',
        'baseurl=https://mirrors.huaweicloud.com/kubernetes/yum/repos/kubernetes-el7-$basearch\n',
        'enabled=1\n',
        'gpgcheck=1\n',
        'repo_gpgcheck=0\n',
        'gpgkey=https://mirrors.huaweicloud.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.huaweicloud.com/kubernetes/yum/doc/rpm-package-key.gpg\n'
    ]
    with open('/etc/yum.repos.d/kubernetes.repo', 'w') as f:
        f.writelines(data)

    if os.system('yum install -y kubelet-%s kubeadm-%s kubectl-%s --disableexcludes=kubernetes >> /dev/null' % (
            k8s_version, k8s_version, k8s_version)) == 0 and os.system(
        'systemctl enable --now kubelet >> /dev/null') == 0:
        return 'kubeadm kubelet kubectl 已部署完毕版本为%s' % (k8s_version)


def install_dockerd_cri():
    path = '/root/cri-dockerd-0.2.6-3.el7.x86_64.rpm'
    dockerd = os.popen('rpm -qa | grep cri-dockerd-0.2.6-3.el7.x86_64').read()
    if not os.path.exists(path) and dockerd != 'cri-dockerd-0.2.6-3.el7.x86_64':
        return '检测到cri-dockerd-0.2.6-3.el7.x86_64.rpm 不存在/root/下，并且环境里没有 cri-dockerd-0.2.6-3.el7.x86_64 新版本k8s依赖这个包使用docker 下载地址为:https://github.com/Mirantis/cri-dockerd/releases/tag/v0.2.6'
    elif os.system('rpm -ivh %s >> /dev/null' % (path)) == 0 and os.popen(
            'rpm -qa | grep cri-dockerd-0.2.6-3.el7.x86_64').read() == 'cri-dockerd-0.2.6-3.el7.x86_64\n':
        os.system('systemctl start cri-docker')
        os.system('systemctl enable cri-docker')
        return 'dockerd-cri安装成功下面开始配置'
    return 'dockerd-cri已经部署无需再次部署'


def setting_CriConfig(old_str, new_str):
    with open('/usr/lib/systemd/system/cri-docker.service', 'r') as f:
        data = f.read()
        if new_str in data:
            return 'cri已经配置,无需再配置'
        with open('/usr/lib/systemd/system/cri-docker.service', 'w') as f:
            new_data = data.replace(old_str, new_str)
            f.writelines(new_data)
        os.system('systemctl daemon-reload && systemctl restart cri-docker.service >> /dev/null')
        os.system('systemctl start cri-docker && systemctl enable cri-docker')
        return 'cri配置成功!'


def setting_kubelet():
    with open('/etc/sysconfig/kubelet', 'w') as f:
        data = 'KUBELET_KUBEADM_ARGS="--container-runtime=remote --container-runtime-endpoint=/run/cri-dockerd.sock"\n'
        f.writelines(data)
        print('kubelet配置成功! 集群初始化需要执行/root/kubernetes_init.py')


print(setting_YumRepo())
print('~~~~~~~~~~正在对环境进行初始化配置~~~~~~~~~~~~~')
stop_firewalld()
setting_hosts()
editHostName()
print(stop_selinux('SELINUX=enforcing', 'SELINUX=disabled'))

print(add_Ipv6Rule())

print(stop_swap('/dev/mapper/centos-swap swap                    swap    defaults        0 0',
                '#/dev/mapper/centos-swap swap                    swap    defaults        0 0'))

print('~~~~~~~~~~~配置完成~~~~~~~~~~~')

print(install_docker())

print('~~~~~~~~~~正在配置和安装kubeadm kubelet kubectl~~~~~~~~~~~~~~')
print(setting_k8sRepo())
setting_kubelet()
print(install_dockerd_cri())

print(setting_CriConfig('ExecStart=/usr/bin/cri-dockerd --container-runtime-endpoint fd://',
                        'ExecStart=/usr/bin/cri-dockerd --container-runtime-endpoint fd:// --network-plugin=cni --cni-bin-dir=/opt/cni/bin --cni-cache-dir=/var/lib/cni/cache --cni-conf-dir=/etc/cni/net.d'))

t1 = input(
    '目前环境初始化已完成后边操作需要在master节点执行,因前边修改了selinux hostname机器需要重启才能生效是否重启?y/n ')
if t1 == 'y' or t1 == 'Y':
    os.system('reboot')
